package com.scheduler.backend.blImpl;

import com.scheduler.backend.aps.domain.deadlinefirst.ScheduleTable;
import com.scheduler.backend.bl.ERPService;
import com.scheduler.backend.data.repository.ItemRepository;
import com.scheduler.backend.data.repository.OrderSliceRepository;
import com.scheduler.backend.data.repository.OrderSliceToEmployeeGroupRepository;
import com.scheduler.backend.data.repository.ResourceGroupRepository;
import com.scheduler.backend.data.repository.ResourceRepository;
import com.scheduler.backend.enums.ItemType;
import com.scheduler.backend.po.Item;
import com.scheduler.backend.po.OrderSlicePO;
import com.scheduler.backend.po.OrderSliceToEmployeeGroup;
import com.scheduler.backend.po.Resource;
import com.scheduler.backend.vo.*;
import org.apache.tomcat.jni.Local;
import com.scheduler.backend.vo.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.time.*;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.Date;
import java.util.List;

@Service
public class ERPServiceImpl implements ERPService {

    private static Logger logger = (Logger) LoggerFactory.getLogger(ERPServiceImpl.class);

    private LocalDateTime scheduleStartTime = LocalDateTime.of(LocalDate.of(2018, 10, 14),
            LocalTime.of(7, 0, 0));;//todo 未来修改

    @Autowired
    private ResourceRepository resourceRepository;

    @Autowired
    private ResourceGroupRepository resourceGroupRepository;

    @Autowired
    private OrderSliceRepository orderSliceRepository;

    @Autowired
    private OrderSliceToEmployeeGroupRepository orderSliceToEmployeeGroupRepository;

    @Autowired
    private ItemRepository itemRepository;

    @Override
    public ResponseVO getDeviceGanttByDate(Date date) {
        try{
            List<DeviceGanttInfo> deviceGanttInfoList = new ArrayList<>();
            List<Resource> oldResources = resourceRepository.findAll();
            List<Resource> newResources = new ArrayList<>();
            List<OrderSlicePO> orderSliceList = orderSliceRepository.findAll();
            orderSliceList.sort(Comparator.comparingLong(OrderSlicePO::getStartTimeSlot));
            for (int i=0;i<oldResources.size();i++){
                Resource resource = oldResources.get(i);
                if (resource.getResourceName().equals("线体")){
                    newResources.add(resource);
                }
            }

            for (int i=0;i<newResources.size();i++){
                Resource resource = newResources.get(i);
                DeviceGanttInfo deviceGanttInfo = new DeviceGanttInfo();
                deviceGanttInfo.setResourceName(resource.getResourceId());
                List<WorkForOrder> workForOrderList = new ArrayList<>();
                for (int j=0;j<orderSliceList.size();j++){
                    if (!orderSliceList.get(j).getEquipmentID().startsWith(resource.getResourceId())) continue;
                    LocalDateTime startTime = scheduleStartTime.plusSeconds(orderSliceList.get(j).getStartTimeSlot() * 60 * ScheduleTable.ORDER_SLICE_MINUTES);
                    LocalDateTime endTime = scheduleStartTime.plusSeconds((orderSliceList.get(j).getStartTimeSlot() + ScheduleTable.ORDER_SLICE_TIMESLOT_SPAN ) * 60 * ScheduleTable.ORDER_SLICE_MINUTES);
                    LocalDateTime today = date.toInstant()
                            .atZone( ZoneId.systemDefault() )
                            .toLocalDateTime();
                    if (startTime.toLocalDate().isEqual(today.toLocalDate())){
                        WorkForOrder workForOrder = new WorkForOrder();
                        workForOrder.setProductName(orderSliceList.get(j).getOrderID());
                        //workForOrder.setItemID(orderSliceList.get(j).getProductID());
                        workForOrder.setStartTime(Date.from(startTime.atZone( ZoneId.systemDefault()).toInstant()));
                        workForOrder.setEndTime(Date.from(endTime.atZone( ZoneId.systemDefault()).toInstant()));
                        workForOrderList.add(workForOrder);
                    }

                }
                deviceGanttInfo.setProducts(workForOrderList);
                deviceGanttInfoList.add(deviceGanttInfo);
            }

            return ResponseVO.buildSuccess(deviceGanttInfoList);
        }catch (Exception e){
            return ResponseVO.buildFailure("getDeviceGanttByDate Failed!");
        }
    }

    @Override
    public ResponseVO getDeviceLoadRatioByDateInHour(Date date) {
        try{
            List<ReUseRatio> reUseRatioList = new ArrayList<>();

            List<Resource> oldResources = resourceRepository.findAll();
            List<Resource> newResources = new ArrayList<>();
            List<OrderSlicePO> orderSliceList = orderSliceRepository.findAll();
            orderSliceList.sort(Comparator.comparingLong(OrderSlicePO::getStartTimeSlot));

            for (int i=0;i<oldResources.size();i++){
                Resource resource = oldResources.get(i);
                if (resource.getResourceName().equals("线体")){
                    newResources.add(resource);
                }
            }

            LocalDateTime thisHour = date.toInstant()
                    .atZone( ZoneId.systemDefault() )
                    .toLocalDateTime();
            LocalDateTime nextHour = thisHour.plusHours(1);

            for (int i=0;i<newResources.size();i++){
                Resource resource = newResources.get(i);
                ReUseRatio reUseRatio = new ReUseRatio();
                reUseRatio.setResourceName(resource.getResourceId());
                double ratio = 0.0;
                double sumUp = 0.0;
                double sumDown = Duration.between(thisHour,nextHour).toMinutes();
                for (int j=0;j<orderSliceList.size();j++){
                    if (!orderSliceList.get(j).getEquipmentID().startsWith(resource.getResourceId())) continue;
                    LocalDateTime startTime = scheduleStartTime.plusSeconds(orderSliceList.get(j).getStartTimeSlot() * 60 * ScheduleTable.ORDER_SLICE_MINUTES);
                    LocalDateTime endTime = scheduleStartTime.plusSeconds((orderSliceList.get(j).getStartTimeSlot() + ScheduleTable.ORDER_SLICE_TIMESLOT_SPAN ) * 60 * ScheduleTable.ORDER_SLICE_MINUTES);

                    if ( (startTime.isEqual(thisHour)||startTime.isAfter(thisHour)) && (endTime.isEqual(nextHour)||endTime.isBefore(nextHour)) ){
                        sumUp += Math.abs(Duration.between(endTime,startTime).toMinutes());
                    }else if ( ((startTime.isEqual(thisHour)||startTime.isAfter(thisHour))) &&  ((startTime.isEqual(nextHour)||startTime.isBefore(nextHour)))){
                        sumUp += Math.abs(Duration.between(nextHour,startTime).toMinutes());
                    }else if (((endTime.isEqual(nextHour)||endTime.isBefore(nextHour))) && ((endTime.isEqual(thisHour)||endTime.isAfter(thisHour)))  ){
                        sumUp += Math.abs(Duration.between(endTime,thisHour).toMinutes());
                    }else if (((startTime.isEqual(thisHour)||startTime.isBefore(thisHour))) && ((endTime.isEqual(nextHour)||endTime.isAfter(nextHour)))){
                        sumUp += Math.abs(Duration.between(nextHour,thisHour).toMinutes());
                    }
                }
                if (sumDown>0.0){
                    ratio = sumUp / sumDown;
                }
                ratio = (double) Math.round(ratio * 1000) / 10;
                reUseRatio.setLoadRatio(ratio);
                reUseRatioList.add(reUseRatio);
            }

            return ResponseVO.buildSuccess(reUseRatioList);
        }catch (Exception e){
            return ResponseVO.buildFailure("getDeviceLoadRatioByDateInHour Failed!");
        }
    }

    @Override
    public ResponseVO getDeviceLoadRatioByDateInDay(Date date) {
        try{
            List<ReUseRatio> reUseRatioList = new ArrayList<>();

            List<Resource> oldResources = resourceRepository.findAll();
            List<Resource> newResources = new ArrayList<>();
            List<OrderSlicePO> orderSliceList = orderSliceRepository.findAll();
            orderSliceList.sort(Comparator.comparingLong(OrderSlicePO::getStartTimeSlot));

            for (int i=0;i<oldResources.size();i++){
                Resource resource = oldResources.get(i);
                if (resource.getResourceName().equals("线体")){
                    newResources.add(resource);
                }
            }

            LocalDateTime today = date.toInstant()
                    .atZone( ZoneId.systemDefault() )
                    .toLocalDateTime();
            LocalDateTime tomorrow = today.plusDays(1);

            for (int i=0;i<newResources.size();i++){
                Resource resource = newResources.get(i);
                ReUseRatio reUseRatio = new ReUseRatio();
                reUseRatio.setResourceName(resource.getResourceId());
                double ratio = 0.0;
                double sumUp = 0.0;
                double sumDown = Duration.between(today,tomorrow).toMinutes();
                for (int j=0;j<orderSliceList.size();j++){
                    if (!orderSliceList.get(j).getEquipmentID().startsWith(resource.getResourceId())) continue;
                    LocalDateTime startTime = scheduleStartTime.plusSeconds(orderSliceList.get(j).getStartTimeSlot() * 60 * ScheduleTable.ORDER_SLICE_MINUTES);
                    LocalDateTime endTime = scheduleStartTime.plusSeconds((orderSliceList.get(j).getStartTimeSlot() + ScheduleTable.ORDER_SLICE_TIMESLOT_SPAN ) * 60 * ScheduleTable.ORDER_SLICE_MINUTES);

                    if (startTime.toLocalDate().isEqual(today.toLocalDate()) && endTime.toLocalDate().isEqual(today.toLocalDate())){
                        sumUp += Math.abs(Duration.between(endTime,startTime).toMinutes());
                    }else if (startTime.toLocalDate().isEqual(today.toLocalDate())){
                        sumUp += Math.abs(Duration.between(tomorrow,startTime).toMinutes());
                    }else if (endTime.toLocalDate().isEqual(today.toLocalDate())){
                        sumUp += Math.abs(Duration.between(today,endTime).toMinutes());
                    }
                }
                if (sumDown>0.0){
                    ratio = sumUp / sumDown;
                }
                ratio = (double) Math.round(ratio * 1000) / 10;
                reUseRatio.setLoadRatio(ratio);

                boolean pd = false;

                reUseRatioList.add(reUseRatio);
            }
            return ResponseVO.buildSuccess(reUseRatioList);
        }catch (Exception e){
            return ResponseVO.buildFailure("getDeviceLoadRatioByDateInDay Failed!");
        }
    }


    @Override
    public ResponseVO getResourceLoadRatio(Date date) {
        try{
            List<ResourceLoadRatioVO> resourceLoadRatioVOList=new ArrayList<>();
            List<Resource> resourceList = resourceRepository.findAll();
            List<OrderSlicePO> orderSlicePOList = orderSliceRepository.findAll();
            List<OrderSliceToEmployeeGroup> orderSliceToEmployeeGroupList = orderSliceToEmployeeGroupRepository.findAll();
            orderSlicePOList.sort(Comparator.comparingLong(OrderSlicePO::getStartTimeSlot));

            LocalDateTime originStartTime = date.toInstant()
                    .atZone( ZoneId.systemDefault() )
                    .toLocalDateTime().plusDays(1).minusDays(7);
            LocalDateTime originEndTime = originStartTime.plusDays(1);

            for (int i=0;i<resourceList.size();i++){
                ResourceLoadRatioVO vo = new ResourceLoadRatioVO();
                vo.setResourceNum(resourceList.get(i).getResourceNum());
                vo.setResourceId(resourceList.get(i).getResourceId());
                if (resourceList.get(i).getResourceName().equals("线体")){
                    vo.setResourceType(1);
                }else{
                    vo.setResourceType(0);
                }
                List<Double> loadRatio=new ArrayList<>();

                LocalDateTime startTime=originStartTime;
                LocalDateTime endTime=originEndTime;
                for (int j=1;j<=7;j++){
                    double ratio = 0.0;
                    double sumUp = 0.0;
                    double sumDown = Duration.between(startTime,endTime).toMinutes();
                    for (int k=0;k<orderSlicePOList.size();k++){
                        boolean pd = false;
                        if (orderSlicePOList.get(k).getEquipmentID().startsWith(vo.getResourceId())){
                            pd = true;
                        }
                        List<OrderSliceToEmployeeGroup> mlist = new ArrayList<>();
                        for (int l=0;l<orderSliceToEmployeeGroupList.size();l++){
                            if (orderSliceToEmployeeGroupList.get(l).getId().equals(orderSlicePOList.get(k).getId())){
                                mlist.add(orderSliceToEmployeeGroupList.get(l));
                            }
                        }
                        if (mlist!=null&&!pd){
                            for (int l=0;l<mlist.size();l++){
                                if (mlist.get(l).getEmployeeGroupID().equals(vo.getResourceId())){
                                    pd=true;
                                    break;
                                }
                            }
                        }
                        if (!pd) continue;
                        LocalDateTime stTime = scheduleStartTime.plusSeconds(orderSlicePOList.get(k).getStartTimeSlot() * 60 * ScheduleTable.ORDER_SLICE_MINUTES);
                        LocalDateTime edTime = scheduleStartTime.plusSeconds((orderSlicePOList.get(k).getStartTimeSlot() + ScheduleTable.ORDER_SLICE_TIMESLOT_SPAN ) * 60 * ScheduleTable.ORDER_SLICE_MINUTES);
                        if (stTime.toLocalDate().isEqual(startTime.toLocalDate()) && edTime.toLocalDate().isEqual(startTime.toLocalDate())){
                            sumUp += Math.abs(Duration.between(stTime,edTime).toMinutes());
                        }else if (stTime.toLocalDate().isEqual(startTime.toLocalDate())){
                            sumUp += Math.abs(Duration.between(endTime,stTime).toMinutes());
                        }else if (edTime.toLocalDate().isEqual(startTime.toLocalDate())){
                            sumUp += Math.abs(Duration.between(startTime,edTime).toMinutes());
                        }

                    }
                    ratio = sumUp/sumDown;
                    ratio = (double) Math.round(ratio * 1000) / 10;

                    loadRatio.add(ratio);
                    startTime=startTime.plusDays(1);
                    endTime=endTime.plusDays(1);
                }

                vo.setLoadRatio(loadRatio);
                resourceLoadRatioVOList.add(vo);
            }
            resourceLoadRatioVOList.sort(Comparator.comparing((p1)->{
                double sum1=0.0;
                for (int i=0;i<p1.getLoadRatio().size();i++)
                    sum1+=p1.getLoadRatio().get(i);
                return -sum1;
            }));

            return ResponseVO.buildSuccess(resourceLoadRatioVOList);
        }catch (Exception e){
            return ResponseVO.buildFailure("getResourceLoadRatio Failed!");
        }
    }


    //获取所有产品（成品 半成品 原始物料）
    @Override
    public ResponseVO getAllItems() {
        try{
            List<Item> itemList=itemRepository.findAll();
            List<ItemVO> itemVOList=new ArrayList<>();
            for(int i=0;i<itemList.size();i++){
                Item item=itemList.get(i);
                ItemVO itemVO=new ItemVO(item.getItemId(),item.getItemDescription(),item.getItemType(),item.getUnit());
                itemVOList.add(itemVO);
            }
            return ResponseVO.buildSuccess(itemVOList);
        }catch (Exception e){
            return ResponseVO.buildFailure("getAllItems Failed!");
        }
    }


}